#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <random>
#include <chrono>
#include <atomic>

using namespace std;

//全局变量
mutex mtx;
condition_variable cv_sender, cv_receiver;
queue<int> packet_queue;//数据包队列
queue<int> ack_queue;//确认包队列
atomic<bool> running{true};//控制线程运行
const int TOTAL_PACKETS = 10;//总发送包数
const double LOSS_PROBABILITY = 0.3;//丢包概率

//随机数生成器
random_device rd;
mt19937 gen(rd());
uniform_real_distribution<> dis(0.0, 1.0);

//发送方线程函数
void sender_thread()
{
    int seq_num = 0;
    int retransmit_count = 0;
    
    while (seq_num < TOTAL_PACKETS && running)
	{
        unique_lock<mutex> lock(mtx);
        
        //发送数据包
        cout << "Sender: Sending packet " << seq_num << endl;
        
        //模拟丢包
        if (dis(gen) > LOSS_PROBABILITY)
		{
            packet_queue.push(seq_num);
            cv_receiver.notify_one();//通知接收方
        }
		else cout << "Sender: Packet " << seq_num << " lost!" << endl;
        
        //等待ACK
        bool ack_received = false;
        auto start = chrono::steady_clock::now();
        
        while (!ack_received && running)
		{
            //设置超时时间
            if (cv_sender.wait_for(lock, chrono::seconds(2)) == cv_status::timeout)
			{
                //超时重传
                retransmit_count++;
                cout << "Sender: Timeout, retransmitting packet " << seq_num << " (retry " << retransmit_count << ")" << endl;
                
                //再次发送，可能再次丢包
                if (dis(gen) > LOSS_PROBABILITY)
				{
                    packet_queue.push(seq_num);
                    cv_receiver.notify_one();
                }
				else cout << "Sender: Retransmitted packet " << seq_num << " also lost!" << endl;
            }
			else
			{
                //收到ACK
                if (!ack_queue.empty())
				{
                    int ack = ack_queue.front();
                    ack_queue.pop();
                    
                    if (ack == seq_num)
					{
                        cout << "Sender: Received ACK for packet " << seq_num << endl;
                        ack_received = true;
                        retransmit_count = 0;
                        seq_num++;
                    }
					else cout << "Sender: Received duplicate ACK for packet " << ack << endl;
                }
            }
        }
    }
    
    cout << "Sender: Transmission complete. Sent " << TOTAL_PACKETS << " packets." << endl;
}

//接收方线程函数
void receiver_thread()
{
    int expected_seq = 0;
    
    while (expected_seq < TOTAL_PACKETS && running)
	{
        unique_lock<mutex> lock(mtx);
        
        //等待数据包
        while (packet_queue.empty() && running)
		{
            cv_receiver.wait(lock);
        }
        
        if (!running) break;
        
        //获取数据包
        int packet = packet_queue.front();
        packet_queue.pop();
        
        //模拟丢包
        if (dis(gen) > LOSS_PROBABILITY)
		{
            cout << "Receiver: Received packet " << packet << ", expecting " << expected_seq << endl;
            
            if (packet == expected_seq)
			{
                // 发送ACK
                cout << "Receiver: Sending ACK for packet " << packet << endl;
                ack_queue.push(packet);
                expected_seq++;
                cv_sender.notify_one();
            }
			else
			{
                //发送重复ACK
                cout << "Receiver: Out-of-order packet, sending duplicate ACK for " << (expected_seq-1) << endl;
                ack_queue.push(expected_seq - 1);
                cv_sender.notify_one();
            }
        }
		else cout << "Receiver: ACK for packet " << packet << " lost!" << endl;
    }
    
    cout << "Receiver: Received all packets." << endl;
}

int main()
{
    cout << "Starting Stop-and-Wait protocol simulation..." << endl;
    cout << "Packet loss probability: " << LOSS_PROBABILITY * 100 << "%" << endl;
    
    thread sender(sender_thread);
    thread receiver(receiver_thread);
    
    //等待一段时间让线程完成工作
    this_thread::sleep_for(chrono::seconds(15));
    
    //通知线程停止
    running = false;
    cv_sender.notify_one();
    cv_receiver.notify_one();
    
    sender.join();
    receiver.join();
    
    cout << "Simulation finished." << endl;
    return 0;
}